<?php
namespace App\Models\Prize;

use App\App\Services\Web\UserService;
use App\Contracts\Repositories\PrizeRepository as PrizeRepositoryContract;
use App\Models\ActivityInfo\ActivityInfo;
use App\Models\ActivityPrize\ActivityPrize;
use App\Models\PrizeRecord\PrizeRecord;
use App\Models\PrizeType\PrizeType;
use App\Models\Sponsor\Sponsor;
use Illuminate\Container\Container;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Redis;

class PrizeRepository implements PrizeRepositoryContract
{
    /**
     * 批量保存关联数据
     * @param $prizes
     */
    public function createAssociation($prizes)
    {
        foreach ($prizes as $prize) {
            $this->create($prize);
        }
    }

    /**
     * 单条保存关联数据
     * @param Prize $data
     * @return bool
     */
    public function create($data)
    {
        DB::beginTransaction();
        try {
            if (is_string($data['prize'])) {
                $prize = json_decode($data['prize'], true);
            } else {
                $prize = $data['prize'];
            }
            Log::error($prize);

            $savedPrize = Prize::create($prize);
            $prize_id = $savedPrize->id;
            if (isset($data['sponsor'])) {
                Sponsor::where('prize_id', $prize_id)->delete();
                if (is_string($data['sponsor'])) {
                    $sponsors = json_decode($data['sponsor'], true);
                } else {
                    $sponsors = $data['sponsor'];
                }
                foreach ($sponsors as $index => $datum) {
                    $sponsors[$index]['prize_id'] = $prize_id;
                }
                Sponsor::insert($sponsors);
            }
            if (is_string($data['prizeRecord'])) {
                $prizeRecord = json_decode($data['prizeRecord'], true);
            } else {
                $prizeRecord = $data['prizeRecord'];
            }
            $prizeRecord['prize_id'] = $prize_id;
            $prizeRecord['created_at'] = date('Y-m-d H:i:s');

            PrizeRecord::create($prizeRecord);
            Log::error('-----------------------------------------------------------');
            Log::error($prize);

            DB::commit();
            return $this->findById($prize_id);
        } catch (\Exception $e) {
            DB::rollback();
            Log::info($e->getMessage());
            return array();
        }
    }

    /**
     * @param $data
     * @param $conditions
     * @return mixed
     */
    public function modify($data, $conditions)
    {
        DB::beginTransaction();
        try {
            if (is_string($data['prize'])) {
                $prize = json_decode($data['prize'], true);
            } else {
                $prize = $data['prize'];
            }
            Prize::where($conditions)->update($prize);
            if (isset($data['sponsor'])) {
                $sponsors = Sponsor::where('prize_id', $conditions['id'])->get();
                if ($sponsors) {
                    Sponsor::where('prize_id', $conditions['id'])->delete();
                }
                if (is_string($data['sponsor'])) {
                    $sponsors = json_decode($data['sponsor'], true);
                } else {
                    $sponsors = $data['sponsor'];
                }
                foreach ($sponsors as $index => $datum) {
                    $sponsors[$index]['prize_id'] = $conditions['id'];
                }
                Sponsor::insert($sponsors);
            }
            DB::commit();
            return $this->findByConditions(array('id' => $conditions['id']), array('prizeType', 'sponsor', 'activity'));
        } catch (\Exception $e) {
            DB::rollback();
            Log::info($e->getMessage());
            return array();
        }
    }

    /**
     * @param $conditions
     * @param bool $softDeletion
     * @return mixed
     */
    public function delete($conditions, $softDeletion = true)
    {
        if ($softDeletion == true) {
            try {
                return Prize::where($conditions)->update(array('deleted_at' => date('Y-m-d H:i:s')));
            } catch (\Exception $e) {
                Log::info($e->getMessage());
                return false;
            }
        } else {
            $prizes = Prize::where($conditions)->get();
            $prizeIds = array_column($prizes->toArray(), 'id');
            DB::beginTransaction();
            try {
                Sponsor::whereIn('prize_id', $prizeIds)->delete();
                PrizeRecord::whereIn('prize_id', $prizeIds)->delete();
                foreach ($prizes as $prize) {
                    $prize->activity()->detach();
                }
                Prize::where($conditions)->delete();
                DB::commit();
                return true;
            } catch (\Exception $e) {
                DB::rollback();
                Log::info($e->getMessage());
                return false;
            }
        }
    }

    public function findById($id)
    {
        $prize_info = Prize::with('prizeType', 'sponsor', 'prizeRecord')->find($id);
        if($prize_info){
            $prize_info = $prize_info->toArray();
        }
        return $prize_info;
    }

    /**
     * @param $typeId
     * @return \Illuminate\Database\Eloquent\Collection|static[]
     */
    public function findByType($typeId)
    {
        return Prize::with('prizeType', 'sponsor')->where('type_code', $typeId)->whereNull('deleted_at')->get();
    }

    /**
     * @param $conditions
     * @param null $withs
     * @param int $limit
     * @param null $offset
     * @return array|\Illuminate\Contracts\Pagination\LengthAwarePaginator
     */
    public function findByConditions($conditions, $withs = null, $limit = 10, $offset = null)
    {
        if (is_array($withs) || is_string($withs) || is_null($withs)) {
            $eloquentObj = Prize::with($withs);
            foreach ($conditions as $index => $item) {
                if (is_array($item)) {
                    if (is_array(end($item))) {
                        $eloquentObj = $eloquentObj->whereIn(reset($item), end($item));
                    } else {
                        $eloquentObj = $eloquentObj->where(array($item));
                    }
                } else {
                    $eloquentObj = $eloquentObj->where(array($index => $item));
                }
            }
            if (!is_null($offset)) {
                $page = ceil($offset / $limit);
                return $eloquentObj->whereNull('deleted_at')->orderBy('created_at','desc')->paginate($limit, ['*'], 'page', $page);
            } else {
                return $eloquentObj->whereNull('deleted_at')->orderBy('created_at','desc')->get()->toArray();
            }
        } else {
            return array();
        }
    }

    /**
     * @param $conditions
     * @param $withs
     * @return array
     */
    public function findDetailByConditions($conditions, $withs)
    {
        $prizeInfos = Prize::with(array('sponsor', 'prizeType', 'activity'))->where($conditions)->whereNull('deleted_at')->get()->toArray();
        if (empty($prizeInfos)) {
            return array();
        }
        $eloquentObj = ActivityInfo::with('ActivityRecord');
        foreach ($prizeInfos as $prizeInfo) {
            $newPrizeinfos[$prizeInfo['id']] = $prizeInfo;
            $activityIds = array_column($prizeInfo['activity'], 'id');
            $activities = $eloquentObj->whereIn('id', $activityIds)->get()->toArray();
            $newPrizeinfos[$prizeInfo['id']]['activity'] = array();
            if (!empty($activities)) {
                foreach ($activities as $activity) {
                    $newPrizeinfos[$prizeInfo['id']]['activity'][] = $activity;
                }
            }
        }
        return $newPrizeinfos;
    }

    public function findPaginateByConditions($conditions, $withs, $limit, $offset)
    {
        if (is_array($withs) || is_string($withs) || is_null($withs)) {
            $page = ceil($offset / $limit);
            $eloquentObj = Prize::with($withs);
            $conditions['whereNull'] = 'deleted_at';
            foreach ($conditions as $key => $condition) {
                if (empty($condition)) {
                    continue;
                }
                if ($key != 'where' && is_array($condition)) {
                    if (is_array(reset($condition))) {
                        $eloquentObj = $eloquentObj->where(function ($query) use ($condition, $key) {
                            foreach ($condition as $item) {
                                $query->$key(array_shift($item), array_shift($item), array_shift($item));
                            }
                        });
                    } else {
                        $eloquentObj = $eloquentObj->$key(reset($condition), end($condition));
                    }
                } else {
                    $eloquentObj = $eloquentObj->$key($condition);
                }
            }
            return $eloquentObj->paginate($limit, ['*'], 'page', $page)->toArray();
        } else {
            return array();
        }
    }

    public function findAvailableWithPaginate($perPage = 15, $kw = null, $columns = ['*'])
    {
        $user = Container::getInstance()->make(UserService::class);

        $query = \App\Entities\Prize::notExpired()->with('type', 'records')
            ->where('group_code', '=', $user->getGroupCode())
            ->where('is_valid', '=', 1)
            ->where('stock_number', '>=', 1);

        if ($kw) {
            $query->where('name', 'LIKE', "%{$kw}%");
        }

        return $query->paginate($perPage, $columns);
    }

    public function batchCreate(array $prizes)
    {
        try {
            DB::beginTransaction();
            $success = \App\Entities\Prize::query()->insert($prizes);
            DB::commit();
        } catch (\PDOException $e) {
            DB::rollBack();
            throw $e;
        }

        return $success;
    }
}
